#include <windows.h>

constexpr auto WINDOW_WIDTH{ 800 };
constexpr auto WINDOW_HEIGHT{ 600 };
constexpr auto CIRCLE_RADIUS{ 20 };

struct Circle {
    int x, y;
};

Circle circle{ WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 };

void DrawCircle(HDC hdc, int x, int y) {
    Ellipse(hdc, x - CIRCLE_RADIUS, y - CIRCLE_RADIUS, x + CIRCLE_RADIUS, y + CIRCLE_RADIUS);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static PAINTSTRUCT ps;
    HDC hdc;

    switch (uMsg) {
    case WM_CREATE:
        SetFocus(hwnd); // Ensure the window has focus to receive key events
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW));
        DrawCircle(hdc, circle.x, circle.y);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_KEYDOWN:
        switch (wParam) {
        case VK_LEFT:
            if (circle.x > CIRCLE_RADIUS) {
                circle.x -= 10; // Move left
            }
            InvalidateRect(hwnd, NULL, TRUE); // Trigger a repaint
            break;
        case VK_RIGHT:
            if (circle.x < WINDOW_WIDTH - 2 * CIRCLE_RADIUS) {
                circle.x += 10; // Move right
            }
            InvalidateRect(hwnd, NULL, TRUE); // Trigger a repaint
            break;
        case VK_UP:
            if (circle.y > CIRCLE_RADIUS) {
                circle.y -= 10; // Move up
            }
            InvalidateRect(hwnd, NULL, TRUE); // Trigger a repaint
            break;
        case VK_DOWN:
            if (circle.y < WINDOW_HEIGHT - 3 * CIRCLE_RADIUS) {
                circle.y += 10; // Move down
            }
            InvalidateRect(hwnd, NULL, TRUE); // Trigger a repaint
            break;
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    const wchar_t CLASS_NAME[] = L"Sample Window Class";

    WNDCLASS wc{};

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        L"Creak Me",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hwnd == NULL) {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    MSG msg{};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}
